﻿using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Zocono.Infrastructure.Common;
using Zocono.WCS.Domain.DomainRepository;
using Zocono.WCS.Domain.EntityInfo;
using Zocono.WCS.Domain.LogDomain;
using Zocono.WCS.Domain.PlcBytesObject;
using Zocono.WCS.Domain.PlcConnectPoolDomain;
using Zocono.WCS.Domain.ProcessModuleDomain;
using Zocono.WCS.Infrastructure.ApllicationDto.Enums;
using Zocono.WCS.WMSApiDomain.WebApi;

namespace Zocono.WCS.Domain.EquipmentProcessDomain.PlanarGeneralMessage
{
    public class UnBinding1Service : IPlanarGeneralPlcActionProcessService
    {
        private readonly ILogUtil _LogUtil;
        private readonly IPlcConnectionPool _PlcConnectionPool; 
        private readonly IPlcWriteDbInfoRepository _PlcWriteDbInfoRepository;
        private readonly IPlcConnectionStateInfoRepository _IPlcConnectionStateInfoRepository;
        private readonly IRunLogInfoService _IRunLogInfoService;
        private readonly IWorkTaskInfoRepository _WorkTaskInfoRepository;

        public UnBinding1Service(ILogUtil logUtil,
             IPlcConnectionPool plcConnectionPool
            , IPlcWriteDbInfoRepository plcWriteDbInfoRepository
            , IWorkTaskInfoRepository workTaskInfoRepository
             , IPlcConnectionStateInfoRepository plcConnectionStateInfoRepository
            , IRunLogInfoService runLogInfoService)
        {
            _LogUtil = logUtil;
            _PlcConnectionPool = plcConnectionPool;
            _PlcWriteDbInfoRepository = plcWriteDbInfoRepository;
            _IPlcConnectionStateInfoRepository = plcConnectionStateInfoRepository;
            _IRunLogInfoService = runLogInfoService;
            _WorkTaskInfoRepository = workTaskInfoRepository;
        }
        public  async Task ProcessActionMessageAsync(BytesObjectBase plcActionMessage, BytesObjectBase wcsActionMessage, EquipmentDbObject planarEquipmentDbObject)
        {
            var plcMessage = plcActionMessage as PlanarGeneralPlcActionBO;//Plc的动作报文
            var wcsMessage = wcsActionMessage as PlanarGeneralWcsActionBO;//Wcs的动作报文
            plcMessage.PalletBarcode = plcMessage.PalletBarcode.Trim();

            RunLogInfo runLogInfo = new()
            {
                ContainerBarcode = plcMessage.PalletBarcode,
                EquipmentCode = plcMessage.EquipmentCode,
                RunType = "托盘解绑",
                RunLog = "托盘解绑任务开始"
            };


            //未执行（待执行）
            //执行中
            //4. 组织报文，写入plc
            var objectType = typeof(PlanarGeneralWriteWcsAction).Name;
            var writeConfig = await _PlcWriteDbInfoRepository.GetFirstAsync(it => it.EquipmentCode == plcMessage.EquipmentCode && it.ObjectType == objectType);
            if (writeConfig == null)
            {
                runLogInfo.RunLog = $"获取PLC写入配置失败";
                //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                _LogUtil.Error(runLogInfo.RunLog);
                return;
            }


            //plc报文什么握手类型则回什么握手类型
            PlanarGeneralWriteWcsAction writeBo = new PlanarGeneralWriteWcsAction(
                writeConfig.PlcConnectionId,
                writeConfig.ID,
                writeConfig.DbCode,
                writeConfig.DbStart,
                objectType,
                plcMessage.EquipmentCode.ToInt32(),
                plcMessage.ActionType,
                //toEquiment.ToInt32(),
                plcMessage.ToEquipmentCode,
                plcMessage.TaskCode,
                plcMessage.PalletBarcode,
                plcMessage.PalletType,
                0);

            //托盘类型
            switch (plcMessage.PalletBarcode.Substring(1, 1))
            {
                case "A":
                    writeBo.PalletType = 2;
                    break;
                case "B":
                    writeBo.PalletType = 1;
                    break;
                case "C":
                    writeBo.PalletType = 3;
                    break;
            }
            var plcConn = _PlcConnectionPool.S7GetWritePlcConnection(writeBo.PlcConnectionID);
            if (plcConn == null)
            {
                runLogInfo.RunLog = $"获取连接({writeBo.PlcConnectionID})失败";
                //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                _LogUtil.Error(runLogInfo.RunLog);
                return;
            }
            var plcIPStates = await _IPlcConnectionStateInfoRepository.GetFirstAsync(l => l.PlcConnectionID == plcMessage.PlcConnectionID && l.Connected == true);
            if (plcIPStates == null)
            {
                runLogInfo.RunLog = $"{plcConn.IP}plc已离线";
                //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                _LogUtil.Error(runLogInfo.RunLog);
                return;
            }
            if (plcMessage.AlrmCode != 0)
            {
                runLogInfo.RunLog = $"报警,报警代码：{plcMessage.AlrmCode}";
                //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                _LogUtil.Error(runLogInfo.RunLog);
                return;
            }
            //3. 验证wcs任务，验证wcs当前子任务
            var exp = Expressionable.Create<WorkTaskInfo>();
            exp.AndIF(true, it => it.PalletCode == plcMessage.PalletBarcode &&it.TaskCode==plcMessage.TaskCode&&it.TaskState==EnumTaskState.Finish);
            var task = await _WorkTaskInfoRepository.GetFirstAsync(exp.ToExpression());

            if (task == null)
            {
                task.TaskState = EnumTaskState.ManualFinish;
                task.CurrentDetailTaskState = EnumDetailTaskState.Finish;
                task.TaskProcessState = EnumTaskProcessState.ScUnloaded;
                task.CurrentUpdateTime = DateTime.Now;
                await _WorkTaskInfoRepository.UpdateAsync(task);
                runLogInfo.RunLog = $"任务号({wcsMessage.TaskCode})完成的任务数据找不到";
                //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                _LogUtil.Error(runLogInfo.RunLog);
            }
            //开始解绑
            task.TaskState = EnumTaskState.ManualFinish;
            task.CurrentDetailTaskState = EnumDetailTaskState.Finish;
            task.TaskProcessState = EnumTaskProcessState.ScUnloaded;
            task.CurrentUpdateTime = DateTime.Now;
            await _WorkTaskInfoRepository.UpdateAsync(task);
            try
            {
                WMSApiDomain.WebApi.HeaderResult<bool> result = await WCSMessageWithWMSApi.UnbandingContainerAsync(plcMessage.PalletBarcode,plcMessage.EquipmentCode,task.WmsTaskCode);


                if (result.IsSucceed)
                {
                    var writeResult = await plcConn.WriteDbAsync(writeBo.DbCode, writeBo.DbStart, writeBo.Deserialize());
                    if (writeResult == false)
                    {
                        runLogInfo.RunLog = $"PLC(IP{plcConn.IP})写入报文失败";
                        //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                        _LogUtil.Error(runLogInfo.RunLog);
                        return;
                    }

                    runLogInfo.RunLog = $"解绑成功并PLC写入报文内容： {JsonConvert.SerializeObject(writeBo)}";
                    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                }
                else
                {
                    writeBo.ActionType = 15;//解绑失败
                    writeBo.AlrmCode = 13;
                    var writeResult = await plcConn.WriteDbAsync(writeBo.DbCode, writeBo.DbStart, writeBo.Deserialize());
                    if (writeResult == false)
                    {
                        runLogInfo.RunLog = $"PLC(IP{plcConn.IP})写入报文失败";
                        //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                        _LogUtil.Error(runLogInfo.RunLog);
                        return;
                    }

                    runLogInfo.RunLog = "解绑失败";
                    //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                    _LogUtil.Error(runLogInfo.RunLog);
                }
            }
            catch 
            {
                runLogInfo.RunLog = $"WMS解绑返回异常,托盘码：{plcMessage.PalletBarcode}";
                //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                _LogUtil.Error(runLogInfo.RunLog);
            }


        }
    }
}
